package com.crazymaker.agent.demo.aop;

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.utility.JavaModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static net.bytebuddy.matcher.ElementMatchers.*;

public class AopTransformer implements AgentBuilder.Transformer {
    private static final Logger LOGGER = LoggerFactory.getLogger(AopTransformer.class);
    private String scanPackage;

    public AopTransformer(String scanPackage) {
        this.scanPackage = scanPackage;
    }

    @Override
    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {
        String targetClassName = typeDescription.getSimpleName();
        System.out.println("----------------------- target class:" + targetClassName);

        if (typeDescription.getPackage().getActualName().equals(scanPackage)
//                    && typeDescription.getInterfaces().size() > 0
//                    && typeDescription.getInterfaces().get(0).getActualName().equals(implInterface)
                ) {
            LOGGER.info("transforming %s...", typeDescription.getTypeName());

            // 委托
            AdviceAdapter adviceAdapter = new AdviceAdapter();
            Aspect aspect = new Aspect();
            aspect.setAdvice(adviceAdapter);

            MethodDelegation methodDelegation =
                    MethodDelegation.withDefaultConfiguration().to(aspect);
            ElementMatcher.Junction<MethodDescription> junction = not(isStatic()).and(named("sayHello"));

//            TypeDescription templateTypeDescription = typePool.describe(templateClassName)
//                    .resolve();
//
//
//            DynamicType.Unloaded interceptorType = new ByteBuddy()
//                    .redefine(templateTypeDescription, ClassFileLocator.ForClassLoader.of(AopTransformer.class.getClassLoader()))
//                    .name(internalInterceptorName)
//                    .field(named("TARGET_INTERCEPTOR")).value(methodsInterceptor)
//                    .make();

            return builder.method(junction).intercept(methodDelegation);
        }

        return builder;


    }
}
